IF (args := ReadArgs(TEMPLATE, arguments, NIL))=NIL THEN Raise(20)
IF ((iconbase<>NIL) AND (buttonbase<>NIL) AND (listbrowserbase<>NIL) AND (chooserbase<>NIL) AND (windowbase<>NIL) AND (layoutbase<>NIL) AND (labelbase<>NIL))
WriteF('\seferred \s refresh \s\n', (IF arguments[A_NODEFER] THEN 'Non-d' ELSE 'D'), (IF arguments[A_SIMPLE] THEN 'Simple' ELSE 'Smart'), (IF arguments[A_NOCARE] THEN '(NoCare)' ELSE ''))
objlist := browserNodesA(objnames)
typelist := chooserLabelsA(objtypes)
/* By providing a message port you enable windowclass to handle iconification
* and appwindows. This port can shared by all the windows of your application.
*/
appport := CreateMsgPort()
IF (objlist AND typelist AND appport)
inithook(apphook,{appMsgFunc},objlist)
/* Create a Window object with a Layout. When Window is asked to open itself,
* it will calculate how much space the Layout needs and size itself accordingly.
*/
window := WindowObject,
WA_IDCMP, IDCMP_RAWKEY,
WA_TOP, 20,
WA_LEFT, 20,
WA_SIZEGADGET, TRUE,
WA_DEPTHGADGET, TRUE,
WA_DRAGBAR, TRUE,
WA_CLOSEGADGET, TRUE,
WA_ACTIVATE, TRUE,
/* About window refreshes:
* Because WindowClass and LayoutClass can, when used together, change the
* normal Intuition practise of refreshing gadgets in the input.device context,
* some rules about the refresh system change.
* Deferred refresh works in both smart and simple refresh windows, but
* if nocarerefresh is used, Intuition does not retain the damage regions
* and any window damage will force the whole window to be refreshed.
* This demo allows you to try combinations of refresh types.
* In the normal case you can ignore this and let WindowClass and the user
* decide what kind of refreshes they want. Nocare refresh can be
* combined with smart refresh to provide a fast, but somewhat more memory
* hungry refresh method. Simple refresh can save some memory but it's
* slower.
*/
WA_SIMPLEREFRESH, arguments[A_SIMPLE],
WA_NOCAREREFRESH, arguments[A_NOCARE],
WA_SMARTREFRESH, Not(arguments[A_SIMPLE]),
WA_TITLE, 'ClassAct layout.gadget Example (ToolManager preferences mockup)',
WA_SCREENTITLE, 'ClassAct Copyright 1995 Phantom Development LLC.',
/* Turn on gadget help in the window
*/
WINDOW_GADGETHELP, TRUE,
/* Add an iconification gadget. If you have this, you must listen to
* WMHI_ICONIFY.
*/
WINDOW_ICONIFYGADGET, TRUE,
/* This message port lets windowclass handle the icon and appwindow.
*/
WINDOW_APPPORT, appport,
WINDOW_APPWINDOW, TRUE,
WINDOW_APPMSGHOOK, apphook,
/* The windowclass will automatically free the DiskObject used when
* iconifying the window. If you do not provide a valid DiskObject,
* windowclass will try to use env:sys/def_window.info or the default
* project icon.
*/
WINDOW_ICON, GetDiskObject( 'LayoutExample' ),
WINDOW_ICONTITLE, 'ClassAct Example',
/* Below is the layout of the window
*/
WINDOW_PARENTGROUP, mainlayout := VGroupObject,
LAYOUT_SPACEOUTER, TRUE,
LAYOUT_BEVELSTYLE, BVS_THIN,
/* this tag instructs layout.gadget to defer GM_LAYOUT and GM_RENDER and ask
* the windowclass to do them. This lessens the load on input.device
*/
LAYOUT_DEFERLAYOUT, Not(arguments[A_NODEFER]),
/* A 1-of-n chooser using the labels list we made from the label array earlier
*/
StartMember, g_objtype := ChooserObject,
CHOOSER_LABELS, typelist,
EndMember,
MemberLabel('_Object Type'),
/* Objects can be given arbitary weights within groups, and layout.gadget
* will distribute space relative to the total weight of the group.
* Here we set the button column to 0 weight which means minimum space.
* Thus the listview gets all available extra space.
*/
StartHGroup, BAligned,
StartMember, g_objlist := ListBrowserObject,
LISTBROWSER_LABELS, objlist,
LISTBROWSER_SHOWSELECTED, TRUE,
EndMember,
StartVGroup,
StartMember, g_top := DButton('Top'),
StartMember, g_up := DButton('Up'),
StartMember, g_down := DButton('Down'),
StartMember, g_bottom := DButton('Bottom'),
StartMember, g_sort := Button('So_rt'),
EndGroup,
CHILD_WEIGHTEDWIDTH, 0,
/* One way to keep the buttons constant size is to set the
* group to stay at minimum size with a weight of 0. We could
* also set the weight of each of the buttons to 0. That way
* extra space would be distributed between the buttons
* instead of all below. This looks better.
*/
CHILD_WEIGHTEDHEIGHT, 0,
EndGroup,
/* two rows of buttons. EvenSized instructs layout.gadget that it
* should make sure the minimum size of each matches, so that we
* get four neat columns.
* Again the weight is set to 0. When the window is resized, all
* space is given to the listview.
*/
StartHGroup, EvenSized,
StartMember, g_new := Button('_New...'),
StartMember, g_edit := DButton('_Edit...'),
StartMember, g_copy := DButton('Co_py'),
StartMember, g_remove := DButton('Remove'),
EndGroup,
CHILD_WEIGHTEDHEIGHT, 0,
StartHGroup, EvenSized,
StartMember, g_save := Button('_Save'),
StartMember, g_use := Button('_Use'),
StartMember, g_test := Button('_Test'),
StartMember, g_cancel := Button('_Cancel'),
EndGroup,
CHILD_WEIGHTEDHEIGHT, 0,
StartMember, g_help := ButtonObject,
GA_READONLY, TRUE,
GA_TEXT, 'Welcome to ClassAct demo!',
EndMember,
CHILD_WEIGHTEDHEIGHT, 0,
EndGroup,
EndWindow
IF window
/* Finish the gadgetarray initialisation. Set gadget IDs and release verify.
* This is one way of avoiding boring repetition in the layout description
* taglist itself.
*/
-> Let's also generate the array of gadget pointers. We couldn't generate it
-> while we created gadgets because some bug (?) in EC prevents the use of
-> an array in the middle of a list.
-> Fortunately, it's a breeze to do using E lists.
gl:=[NIL,
g_objtype,
g_objlist,
g_top,
g_up,
g_down,
g_bottom,
g_sort,
g_new,
g_edit,
g_copy,
g_remove,
g_help,
g_save,
g_use,
g_test,
g_cancel,
NIL]
i:=1
REPEAT
SetAttrsA(gl[i], [GA_ID, i, GA_RELVERIFY, TRUE, TAG_END])
INC i
UNTIL (i = G_END)
IF (win := CA_OpenWindow(window))
asig := Shl(1,appport.sigbit)
/* Now that the window has been opened, we can get the signal mask
* of its user port. If the program supported iconification and didn't
* use a shared IDCMP port between all windows, this signal bit
* would have to be re-queried before each Wait().
*/
GetAttr( WINDOW_SIGMASK, window, {wsig} )
WHILE (done = FALSE)
sig := Wait(wsig OR asig OR SIGBREAKF_CTRL_C)
IF (sig AND (wsig OR asig))
/* Messages waiting at the window's IDCMP port. Loop at WM_HANDLEINPUT
* until all have been processed.
*/
WHILE ((result := CA_HandleInput(window,{code})) <> WMHI_LASTMSG)
/* The return code of this method is two-part. The upper word describes the
* class of the message (gadgetup, menupick, closewindow, iconify, etc),
* and the lower word is a class-defined ID, currently in use in the
* gadgetup and menupick return codes.
* Switch on the class, then on the ID.
*/
tmp := (result AND WMHI_CLASSMASK)
SELECT tmp
CASE WMHI_GADGETUP
/* OK, got a gadgetup from something. Lets find out what the something is.
* The code WORD to which a pointer was passed to WM_HANDLEINPUT has been
* set to the Code value from the IDCMP_GADGETUP, in case we need it.
*/
tmp2 := (result AND WMHI_GADGETMASK)
SELECT tmp2
CASE G_OBJLIST
/* User clicked on the listview
*/
IF (code = Not(0)) THEN dis := TRUE /* no node was selected */